package com.ruoyi.consumer.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.consumer.domain.CCompany;
import com.ruoyi.consumer.domain.CFillingFacilit;
import com.ruoyi.consumer.domain.CStatisticTable;
import com.ruoyi.consumer.domain.CUser;
import com.ruoyi.consumer.domain.param.CStatisticTableParam;
import com.ruoyi.consumer.mapper.CStatisticTableMapper;
import com.ruoyi.consumer.service.ICCompanyService;
import com.ruoyi.consumer.service.ICFillingFacilitService;
import com.ruoyi.consumer.service.ICStatisticTableService;
import com.ruoyi.consumer.service.ICUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.stereotype.Service;

import java.text.DecimalFormat;
import java.util.*;
import java.util.List;
import java.util.concurrent.*;
import java.util.stream.Collectors;


/**
 * 统计总Service业务层处理
 *
 * @author YFENTEST
 * @date 2024-03-11
 */
@Service
public class CStatisticTableServiceImpl implements ICStatisticTableService {
    @Autowired
    private CStatisticTableMapper cStatisticTableMapper;
    @Autowired
    private ICStatisticTableService cStatisticTableService;
    @Autowired
    private ICCompanyService companyService;
    @Autowired
    private ICFillingFacilitService facilitService;
    @Autowired
    private ICUserService userService;

    /**
     * 查询统计总
     *
     * @param statisticId 统计总主键
     * @return 统计总
     */
    @Override
    public CStatisticTable selectCStatisticTableByStatisticId(Integer statisticId) {
        return cStatisticTableMapper.selectCStatisticTableByStatisticId(statisticId);
    }

    /**
     * 查询统计总列表
     *
     * @param cStatisticTable 统计总
     * @return 统计总
     */
    @Override
    public List<CStatisticTable> selectCStatisticTableList(CStatisticTable cStatisticTable) {
        return cStatisticTableMapper.selectCStatisticTableList(cStatisticTable);
    }

    /**
     * 新增统计总
     *
     * @param cStatisticTable 统计总
     * @return 结果
     */
    @Override
    public int insertCStatisticTable(CStatisticTable cStatisticTable) {
        cStatisticTable.setCreateTime(DateUtils.getNowDate());
        return cStatisticTableMapper.insertCStatisticTable(cStatisticTable);
    }

    /**
     * 修改统计总
     *
     * @param cStatisticTable 统计总
     * @return 结果
     */
    @Override
    public int updateCStatisticTable(CStatisticTable cStatisticTable) {
        cStatisticTable.setUpdateTime(DateUtils.getNowDate());
        return cStatisticTableMapper.updateCStatisticTable(cStatisticTable);
    }

    /**
     * 批量删除统计总
     *
     * @param statisticIds 需要删除的统计总主键
     * @return 结果
     */
    @Override
    public int deleteCStatisticTableByStatisticIds(Integer[] statisticIds) {
        return cStatisticTableMapper.deleteCStatisticTableByStatisticIds(statisticIds);
    }

    /**
     * 删除统计总信息
     *
     * @param statisticId 统计总主键
     * @return 结果
     */
    @Override
    public int deleteCStatisticTableByStatisticId(Integer statisticId) {
        return cStatisticTableMapper.deleteCStatisticTableByStatisticId(statisticId);
    }

    @Override
    public List<CStatisticTable> getcStatisticTables(CStatisticTable cStatisticTable, List<CStatisticTableParam> resultList) {
        List<CStatisticTable> list = cStatisticTableService.selectCStatisticTableList(cStatisticTable);
        // 去重后的companyIdToIds
        Map<Integer, Integer> companyIdToIds = list.stream()
                .filter(item -> ObjectUtil.isNotNull(item.getCompanyId()) && item.getCompanyId() != 0)
                .collect(Collectors.toMap(
                                CStatisticTable::getCompanyId,
                                CStatisticTable::getStatisticId,
                                (existiing, replacement) -> existiing,
                                LinkedHashMap::new
                        )
                );
        // 去重后的facilitIdToIds
        Map<Integer, Integer> facilitIdToIds = list.stream()
                .filter(item -> ObjectUtil.isNotNull(item.getFacilitId()) && item.getFacilitId() != 0)
                .collect(Collectors.toMap(
                                CStatisticTable::getFacilitId,
                                CStatisticTable::getStatisticId,
                                (existiing, replacement) -> existiing,
                                LinkedHashMap::new
                        )
                );
        Map<Integer, Integer> mangerIdTOIds = list.stream()
                .filter(item -> ObjectUtil.isNotNull(item.getMangerId()) && item.getMangerId() != 0)
                .collect(Collectors.toMap(
                                CStatisticTable::getMangerId,
                                CStatisticTable::getStatisticId,
                                (existiing, replacement) -> existiing,
                                LinkedHashMap::new
                        )
                );

        // 创建一个线程池
        ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(15);

        // 并发查询唯一的 FacilitId 对应的 FacilitName
        Map<Integer, CompletableFuture<String>> facilitNameFutures = facilitIdToIds.keySet().stream()
                .filter(Objects::nonNull)
                .collect(Collectors.toMap(
                        id -> id,
                        id -> CompletableFuture.supplyAsync(() -> {
                            try {
                                CFillingFacilit facilit = facilitService.selectCFillingFacilitByFacilitId(id);
                                return ObjectUtil.isNotEmpty(facilit.getFacilitName()) ? facilit.getFacilitName() : null;
                            } catch (Exception e) {
                                e.printStackTrace();
                                return null;
                            }
                        }, executor)
                ));
        Map<Integer, CompletableFuture<String>> companyNameFutures = companyIdToIds.keySet().stream()
                .filter(Objects::nonNull)
                .collect(Collectors.toMap(
                        id -> id,
                        id -> CompletableFuture.supplyAsync(() -> {
                            try {
                                CCompany company = companyService.selectCCompanyByCompanyId(id);
                                return ObjectUtil.isNotEmpty(company.getCompanyName()) ? company.getCompanyName() : null;
                            } catch (Exception e) {
                                e.printStackTrace();
                                return null;
                            }
                        }, executor)
                ));
        Map<Integer, CompletableFuture<String>> mangerNameFutures = mangerIdTOIds.keySet().stream()
                .filter(Objects::nonNull)
                .collect(Collectors.toMap(
                        id -> id,
                        id -> CompletableFuture.supplyAsync(() -> {
                            try {
                                CUser user = userService.selectCUserByUserId(id);
                                return ObjectUtil.isNotEmpty(user.getUserName()) ? user.getUserName() : user.getUserNick();
                            } catch (Exception e) {
                                e.printStackTrace();
                                return null;
                            }
                        }, executor)
                ));

        // 等待所有的 CompletableFuture 完成并收集结果到 Map 中
        Map<Integer, String> companyNames = companyNameFutures.entrySet().stream()
                .collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().join()));

        Map<Integer, String> facilitNames = facilitNameFutures.entrySet().stream()
                .collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().join()));

        Map<Integer, String> mangerNames = mangerNameFutures.entrySet().stream()
                .collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().join()));

        // 使用并发任务来填充 CStatisticTableParam 对象列表
        List<CompletableFuture<Void>> futures = list.stream()
                .map(item -> CompletableFuture.runAsync(() -> {
                    CStatisticTableParam param = new CStatisticTableParam();
                    param.setStatisticId(item.getStatisticId());
                    param.setUserName(item.getUserName());
                    param.setPlateNum(item.getPlateNum());
                    param.setOrderMoney(getMoney(item.getOrderMoney()));
                    param.setSn(item.getSn());
                    param.setOrderFilled(getKg(Math.toIntExact(item.getOrderFilled())));
                    param.setFacilitLng(item.getFacilitLng());
                    param.setFacilitLat(item.getFacilitLat());
                    param.setOrderPrice(getMoney(item.getOrderPrice()).toString());
                    param.setStatisticType(item.getStatisticType());
                    param.setUpdateTime(item.getUpdateTime());
                    param.setFillTime(item.getUpdateTime());
                    if (companyNames.containsKey(item.getCompanyId())) {
                        param.setCompanyName(companyNames.get(item.getCompanyId()));
                    }
                    if (facilitNames.containsKey(item.getFacilitId())) {
                        param.setFacilitName(facilitNames.get(item.getFacilitId()));
                    }
                    if (mangerNames.containsKey(item.getMangerId())) {
                        param.setMangerName(mangerNames.get(item.getMangerId()));
                    }

                    switch (item.getStatisticType()) {
                        case 1:
                            param.setStatisticTypeExport("公司钱包");
                            break;
                        case 2:
                            param.setStatisticTypeExport("个人钱包");
                            break;
                        case 3:
                            param.setStatisticTypeExport("微信支付");
                            break;
                        default:
                            param.setStatisticTypeExport("未知");
                            break;
                    }
                    synchronized (resultList) {
                        resultList.add(param);
                    }
                }, executor))
                .collect(Collectors.toList());

        // 等待所有的填充任务完成
        CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
        // 时间排序
        resultList.sort((param1, param2) -> {
            Date time1 = param1.getUpdateTime();
            Date time2 = param2.getUpdateTime();
            if (ObjectUtil.isNull(time1) && ObjectUtil.isNull(time2)) return 0;
            if (ObjectUtil.isNull(time1)) return 1;
            if (ObjectUtil.isNull(time2)) return -1;
            return time2.compareTo(time1);
        });

        // 关闭线程池
        executor.shutdown();

        return list;
    }

    //将分换成元保留两位小数
    public String getMoney(Integer money) {
        String str = String.valueOf(money);
        if (str.length() == 1) {
            str = "0.0" + str;
        } else if (str.length() == 2) {
            str = "0." + str;
        } else {
            str = str.substring(0, str.length() - 2) + "." + str.substring(str.length() - 2);
        }
        return str;
    }

    // 将克(g)转换为千克(kg)并保留两位小数
    public String getKg(Integer g) {
        double kg = g / 1000.0; // 将克转换为千克
        // 使用DecimalFormat来保留两位小数并格式化输出
        DecimalFormat df = new DecimalFormat("#.##");
        return df.format(kg);
    }


}
